/*
 *  ckr_spec_SpecRunner.h
 *  ckrSpec
 *
 *  Created by C. Keith Ray on 2006.11.06.
 *  Copyright 2006 __MyCompanyName__. All rights reserved.
 *
 */

#pragma once

#include <iosfwd>
#include <exception>
#include <string>
#include <sstream>
#include <vector>

namespace  ckr
{
	class Context;
	typedef std::vector<Context*> ContextList;

	class SpecListener;

	class SpecRunner
	{
	public:
		
		static SpecRunner* getGlobalSpecRunner();

		SpecRunner();
		virtual ~SpecRunner();
		
		virtual SpecRunner& add( Context* aContext );

		virtual unsigned int numSpecs();

		virtual void runAll( SpecListener* listenerIn );
		virtual void runFastOnly( SpecListener* listenerIn );
		virtual void runNewFirst( SpecListener* listenerIn );
		virtual void runFailingFirst( SpecListener* listenerIn );

		virtual unsigned int numSpecsPassing() const;
		virtual unsigned int numSpecsFailing() const;

		virtual ContextList passingSpecs() const;
		virtual ContextList failingSpecs() const;
		virtual ContextList fastSpecs() const;
		virtual ContextList newSpecs() const;

		virtual ContextList allSpecs() const;
			// specs are in case-insensitive alphabetical order

		virtual double totalSpecDuration();

	protected:

		ContextList myContextList; // we do not OWN these pointers

		double averageDuration() const;
		void sortSpecsFastestFirst();
		void sortSpecsNotYetRunFirst();
		void sortSpecsFailingFirst();

		void runOne( Context* aContext, SpecListener* listenerIn );
	};

	// RegisterContextWithRunner is used behind the scenes via
	// the IMPLEMENT_SPEC macro.
	// Don't use it directly.
	class RegisterContextWithRunner
	{
	public:
		RegisterContextWithRunner( 
					Context*				aContext,
					SpecRunner*			aRunner );
	};

}; // end namespace

